package com.xquant.pricing.calc.service.impl.otcOption;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.xquant.common.core.constant.DictConstant;
import com.xquant.pricing.calc.entity.CalcEngineParam4Simple;
import com.xquant.pricing.calc.entity.simple.Header;
import com.xquant.pricing.calc.entity.simple.OptionTrade;
import com.xquant.pricing.calc.entity.simple.Record;
import com.xquant.pricing.calc.service.impl.otcOption.split.CalcCommonService4OtcOptionSplit;
import com.xquant.common.engine.xPP.request.CalcEngineParam;
import com.xquant.common.engine.xPP.request.CalcPricingParam;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @Author: xpp -_- -_-
 * @Date: 2021/11/2 9:31
 */
@Service
public class CalcCommonService4OtcOptionSplitService implements InitializingBean {

    @Autowired
    private List<CalcCommonService4OtcOptionSplit> otcOptionSplits;

    private Map<String, CalcCommonService4OtcOptionSplit> splitMap = new HashMap<>();

    private final static String[] customArr = new String[]{
            DictConstant.OPTION_TYPE.SHARK.getCode().toLowerCase(Locale.ROOT),
            DictConstant.OPTION_TYPE.DOUBLE_SHARK.getCode().toLowerCase(Locale.ROOT),
            DictConstant.OPTION_TYPE.AIRBAG.getCode().toLowerCase(Locale.ROOT),/*,
            DictConstant.OPTION_TYPE.ELN_ACB_VANILLASPREAD.getCode().toLowerCase(Locale.ROOT)*/
    };


    @Override
    public void afterPropertiesSet() throws Exception {
        for (CalcCommonService4OtcOptionSplit otcOptionSplit : otcOptionSplits) {
            splitMap.put(otcOptionSplit.getSplitCode(), otcOptionSplit);
        }
    }

    public CalcCommonService4OtcOptionSplit getDelegateService(String productType) {
        return splitMap.get(DictConstant.OPTION_TYPE.getEnumType(productType).getCode());
    }

    public CalcEngineParam beforeCalc(CalcEngineParam param) {
        List<String> strings = Arrays.asList(customArr);
        //取出定价参数设置
        if (ObjectUtil.isNull(param) || ObjectUtil.isNull(param.getInstrument())) {
            throw new RuntimeException("条款为空！");
        }
        CalcPricingParam calcPricingParam = param.getCalcPricingParam();
        if (ObjectUtil.isNull(param.getInstrument().getTermsheet())) {
            return param;
        }
        JSONObject termsheet = param.getInstrument().getTermsheet();
        Optional<Object> optional = Optional.ofNullable(termsheet.get("customLegs"));
        if (!optional.isPresent()) {
            return param;
        }


        if (strings.contains(param.getInstrument().getProductType().toLowerCase(Locale.ROOT))) {

            String numberOfOptions = "1";
            ArrayList customLegs = new ArrayList<String>();
            JSONArray customLegsJsonArray = new JSONArray();
            LinkedHashMap customLeg = new LinkedHashMap<>();
            JSONObject customLegJsonObject = new JSONObject();
            LinkedHashMap optionTrade = new LinkedHashMap<>();
            JSONObject optionTradeJsonObject = new JSONObject();
            String optionTradeStr = null;
            String headStr = null;

            if (optional.get() instanceof JSONArray) {
                customLegsJsonArray = (JSONArray) (optional.get());
                customLegJsonObject = (JSONObject) customLegsJsonArray.get(0);
                if (StrUtil.isNotBlank(customLegJsonObject.getString("numberOfOptions"))) {
                    numberOfOptions = customLegJsonObject.getString("numberOfOptions");
                }
                optionTradeJsonObject = customLegJsonObject.getJSONObject("OptionTrade");
                optionTradeStr = JSON.toJSONString(optionTradeJsonObject);
            } else {
                customLegs = (ArrayList) optional.get();
                customLeg = (LinkedHashMap) customLegs.get(0);
                if (ObjectUtil.isNull(customLeg)) {
                    return null;
                }
                optionTrade = (LinkedHashMap) customLeg.get("OptionTrade");
                optionTradeStr = JSON.toJSONString(optionTrade);
            }

            CalcEngineParam4Simple calcEngineParam4Simple = new CalcEngineParam4Simple();
            Header header = new Header();
            Record record = new Record();
            String valueDate = param.getCalcPricingParam().getValueDate();
            header.setTimestmp(DateUtil.format(DateUtil.parse(valueDate), "yyyyMMdd HH:mm:ss"));
            OptionTrade optionTrade1 = JSON.parseObject(optionTradeStr, OptionTrade.class);
            record.setOptionTrade(optionTrade1);
            record.setNumberOfOptions(numberOfOptions);
            calcEngineParam4Simple.setRecord(record);
            calcEngineParam4Simple.setHeader(header);
            CalcCommonService4OtcOptionSplit delegateService;
            if ("null".equals(optionTradeStr)) {
                delegateService = this.getDelegateService(param.getInstrument().getProductType());
                param = delegateService.split(param);
                if (ObjectUtil.isNull(delegateService)) {
                    throw new RuntimeException("尚未支持该类型的产品！");
                }
            } else {
                delegateService = this.getDelegateService(calcEngineParam4Simple.getRecord().getOptionTrade().getOptionLegs().get(0).getProductType());
                if (ObjectUtil.isNull(delegateService)) {
                    throw new RuntimeException("尚未支持该类型的产品！");
                }
                param = delegateService.split(calcEngineParam4Simple);
            }
            param.setCalcPricingParam(calcPricingParam);
        }
        return param;
    }

}
